"""
Case Type   : 系统内部使用工具
Case Name   : 1+2备在被减容的备库卸载再执行扩容加回集群，再进行减容备1
Create At   : 2022/04/11
Owner       : opentestcase018
Description :
    1.执行gs_dropnode进行减容
    2.在减容备机上执行gs_uninstall --delete-data卸载数据库
    3.扩容被减容备机
    4.再次执行gs_dropnode进行减容：
    5.清理环境
Expect      :
    1.成功
    2.成功
    3.成功
    4.成功
    5.成功
History     :
    2022-6-06 opentestcase039 优化用例，根据自动化连跑要求，改为在源库上操作
    2022-7-01 opentestcase039 优化用例，增加检查gs_sshexkey工具步骤
    2022-8-03 opentestcase039 优化用例，增加检查stand_name后断言
    2022-8-26 opentestcase039 优化用例，研发代码变更，待扩容备机未安装数据库扩容不需要输入密码
    2023-4-20 opentestcase039 优化用例，扩容前增加解压安装包步骤
    2023-5-11 opentestcase039 优化用例，增加scp om包步骤
"""
import os
import unittest

from testcase.utils.Common import Common
from testcase.utils.Common import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro

COMMONSH = CommonSH("PrimaryDbUser")
Constant = Constant()


@unittest.skipIf(3 != COMMONSH.get_node_num(), '非1+2环境不执行')
class Tools(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.common = Common()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.primary_root_node = Node('PrimaryRoot')
        self.primary_node = Node('PrimaryDbUser')
        self.standby1_root_node = Node('Standby1Root')
        self.standby1_node = Node('Standby1DbUser')
        self.standby2_node = Node('Standby2DbUser')
        self.standby2_root_node = Node('Standby2Root')
        self.com_root = CommonSH("PrimaryRoot")
        self.com_user = CommonSH("PrimaryDbUser")
        self.s_com1 = CommonSH("Standby1DbUser")
        self.s_com2 = CommonSH("Standby2DbUser")
        self.u_name = self.primary_node.ssh_user
        num = COMMONSH.get_node_num()
        self.assertGreaterEqual(num, 3, "执行失败:节点数量异常，减容不执行")
        self.log.info("查询synchronous_standby_names默认值")
        result = COMMONSH.execut_db_sql("show synchronous_standby_names")
        self.assertIn('synchronous_standby_names', result, '获取失败')
        self.log.info(f"primary synchronous_standby_names is {result}")
        self.synchronous_standby_names_p = result.strip().splitlines()[-2]
        result = self.s_com1.execut_db_sql("show synchronous_standby_names")
        self.assertIn('synchronous_standby_names', result, '获取失败')
        self.log.info(f"s1 synchronous_standby_names is {result}")
        self.synchronous_standby_names_s1 = result.strip().splitlines()[-2]
        result = self.s_com2.execut_db_sql("show synchronous_standby_names")
        self.assertIn('synchronous_standby_names', result, '获取失败')
        self.log.info(f"s2 synchronous_standby_names is {result}")
        self.synchronous_standby_names_s2 = result.strip().splitlines()[-2]

        self.host_tuple = (self.primary_node.ssh_host,
                           self.standby1_node.ssh_host,
                           self.standby2_node.ssh_host)
        self.params = {'-f': 'test_hosts'}

    def test_gs_dropnode(self):
        text = '----step1:执行gs_dropnode进行备机减容 expect:成功----'
        self.log.info(text)
        drop_cmd = f'gs_dropnode -U {self.u_name} -G {self.u_name} ' \
                   f'-h {self.standby1_node.ssh_host}'
        self.log.info(drop_cmd)
        global shell_path
        shell_path = os.path.join('/', 'home', f'{self.u_name}', 'dropnode.sh')
        shell_cmd = f'touch {shell_path};echo -e {drop_cmd} > {shell_path};' \
                    f'chmod 755 {shell_path};cat {shell_path}'
        self.log.info(shell_cmd)
        shell_res = self.primary_root_node.sh(shell_cmd).result()
        self.log.info(shell_res)
        drop_cmd = f'''source {macro.DB_ENV_PATH}
                       expect <<EOF
                       set timeout 200
                       spawn {shell_path}
                       expect "(yes/no)?"
                       send "yes\\n"
                       expect eof\n''' + '''EOF'''
        self.log.info(drop_cmd)
        drop_res = self.primary_node.sh(drop_cmd).result()
        self.log.info(drop_res)
        self.assertIn('Success to drop the target nodes', drop_res,
                      text + '减容失败')

        self.log.info('检查数据库是否减容')
        check_cmd = f'source {macro.DB_ENV_PATH};' \
                    f'gs_om -t status --detail;'
        self.log.info(check_cmd)
        check_res = self.primary_node.sh(check_cmd).result()
        self.log.info(check_res)
        self.assertNotIn(self.standby1_node.ssh_host, check_res, '数据库状态检查失败')

        text = "----step2:在减容备机上执行卸载数据库 expect:成功----"
        self.log.info(text)
        text_1 = '----gs_uninstall卸载数据库----'
        self.log.info(text_1)
        execute_cmd = f'source {macro.DB_ENV_PATH};' \
                      f'gs_uninstall --delete-data -L;'
        self.log.info(execute_cmd)
        uninstall_msg = self.standby1_node.sh(execute_cmd).result()
        self.log.info(uninstall_msg)
        self.assertIn(Constant.uninstall_success_msg, uninstall_msg, '卸载失败')

        text = '----step3:执行gs_expansion进行备机扩容 expect:成功----'
        self.log.info(text)
        self.log.info('-----创建root互信-----')
        result = self.common.get_sh_result(self.primary_root_node,
                                           f"ls {macro.DB_SCRIPT_PATH}")
        if "gs_sshexkey" not in result:
            cmd = f"cd {os.path.dirname(macro.DB_SCRIPT_PATH)};" \
                  f"tar -zxvf openGauss-Package-bak*.tar.gz > /dev/null"
            self.log.info('-----解压bak包-----')
            self.common.get_sh_result(self.primary_root_node, cmd)
            result = self.common.get_sh_result(self.primary_root_node,
                                               f'ls {macro.DB_SCRIPT_PATH}')
            self.assertIn("gs_sshexkey", result, "找不到安装包")

        self.com_root.exec_gs_sshexkey(macro.DB_SCRIPT_PATH,
                                       *self.host_tuple,
                                       **self.params)
        cmd1 = f"cd {os.path.dirname(macro.DB_SCRIPT_PATH)};" \
               f"scp *om.tar.gz " \
               f"root@{self.primary_node.ssh_host}:" \
               f"{os.path.dirname(macro.DB_SCRIPT_PATH)}"
        self.common.get_sh_result(self.standby2_root_node, cmd1)
        expansion_cmd = f'cd {macro.DB_SCRIPT_PATH};' \
                        f'source {macro.DB_ENV_PATH};' \
                        f'./gs_expansion -U {self.u_name} -G {self.u_name} ' \
                        f'-X {macro.DB_XML_PATH} -h ' \
                        f'{self.standby1_node.ssh_host}'
        self.log.info(expansion_cmd)
        expan_result = self.common.get_sh_result(self.primary_root_node,
                                                 expansion_cmd)
        check_msg = f'Expansion results:\n' \
                    f'{self.standby1_node.ssh_host}:\tSuccess\n' \
                    f'Expansion Finish.'
        self.assertIn(check_msg, expan_result, text + '执行失败')
        self.log.info('检查是否扩容成功')
        check_cmd = f"source {macro.DB_ENV_PATH};" \
                    f"gs_om -t status --detail"
        check_res = self.primary_node.sh(check_cmd).result()
        for check in [self.primary_node.ssh_host, self.standby1_node.ssh_host,
                      self.standby2_node.ssh_host]:
            self.assertIn(check, check_res, '扩容后检查失败')

        text = '----step4:再次执行gs_dropnode进行备机减容 expect:成功----'
        self.log.info(text)
        drop_res = self.primary_node.sh(drop_cmd).result()
        self.log.info(drop_res)
        self.assertIn('Success to drop the target nodes', drop_res,
                      text + '减容失败')

        self.log.info('检查数据库是否减容')
        check_cmd = f'source {macro.DB_ENV_PATH};' \
                    f'gs_om -t status --detail;'
        self.log.info(check_cmd)
        check_res = self.primary_node.sh(check_cmd).result()
        self.log.info(check_res)
        self.assertNotIn(self.standby1_node.ssh_host, check_res, '数据库状态检查失败')

    def tearDown(self):
        text = "----step5:清理用户及文件 expect:成功----"
        self.log.info(text)
        self.log.info('-----创建root互信-----')
        result = self.common.get_sh_result(self.primary_root_node,
                                           f"ls {macro.DB_SCRIPT_PATH}")
        if "gs_sshexkey" not in result:
            cmd = f"cd {macro.DB_SCRIPT_PATH}/../; " \
                  f"tar -zxvf openGauss-Package-bak*.tar.gz > /dev/null"
            result = self.primary_root_node.sh(cmd).result()
            self.log.info(result)
            result = self.common.get_sh_result(self.primary_root_node,
                                               f"ls {macro.DB_SCRIPT_PATH}")
            self.log.info(result)
            if "gs_sshexkey" not in result:
                raise Exception("cat not find gs_sshexkey, Please check!")

        self.com_root.exec_gs_sshexkey(macro.DB_SCRIPT_PATH,
                                       *self.host_tuple,
                                       **self.params)
        result = self.com_root.exec_expension(f"{self.primary_node.ssh_user}",
                                              f"{self.primary_node.ssh_user}",
                                              f"{self.standby1_node.ssh_host}",
                                              f"{macro.DB_XML_PATH}")
        self.log.info(result)
        self.log.info('-----删除创建文件-----')
        del_cmd = f"rm -rf {shell_path}"
        self.log.info(del_cmd)
        del_res = self.primary_root_node.sh(del_cmd).result()
        self.log.info(del_res)
        self.log.info("恢复各节点synchronous_standby_names")
        COMMONSH.execute_gsguc("reload",
                               Constant.GSGUC_SUCCESS_MSG,
                               f"synchronous_standby_names="
                               f"'{self.synchronous_standby_names_p}'",
                               single=True)
        self.s_com1.execute_gsguc("reload",
                                  Constant.GSGUC_SUCCESS_MSG,
                                  f"synchronous_standby_names="
                                  f"'{self.synchronous_standby_names_s1}'",
                                  single=True)
        self.s_com2.execute_gsguc("reload",
                                  Constant.GSGUC_SUCCESS_MSG,
                                  f"synchronous_standby_names="
                                  f"'{self.synchronous_standby_names_s2}'",
                                  single=True)
        self.assertEqual('', del_res, '文件删除失败')
        self.assertTrue(result)
        self.log.info(f'----{os.path.basename(__file__)} finish----')
